package controllers

import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"strings"
)

type importLines [] string

var GoPackageAllLib = [...]string {"archive","bufio","builtin","bytes","cmd","compress","container",
	"context","crypto","database","debug","encoding","errors","expvar","flag","fmt","go","hash","html",
	"image","index","internal","io","math","mime","net","os","path","plugin","replect","regexp","runtime",
	"sort","strconv","strings","sync","syscall","testdata","testing","text","time","unicode","unsafe","reflect"}
var PackageClassify = make(map[string]importLines)


func parseGoProject(projectPath string,filterKeywords string){
	PackageClassify =make(map[string]importLines)
	var s []string
	s,e  := GetAllFile(projectPath,s)
	if e != nil{
		fmt.Println(e)
		return
	}
	var selectLines importLines
	for x:=0;x<len(s);x++{
		readGoFileImport(s[x],&selectLines)
	}
	FilterKeywords(filterKeywords,&selectLines)
	selectLines = removeDuplicateElement(selectLines)
	for x:=0;x<len(selectLines);{
		line := selectLines[x]
		golibDel := false
		for _,golibName := range GoPackageAllLib{
			if golibName ==line || (strings.Contains(line,"/")&&golibName == line[0:strings.Index(line,"/")]){
				golib :=PackageClassify["golib"]
				golib = append(golib, line)
				PackageClassify["golib"] = golib
				golibDel = true
				break;
			}
		}
		if golibDel{
			selectLines = append(selectLines[:x],selectLines[x+1:]...)
		}else if strings.HasPrefix(line,"github") {
			github :=PackageClassify["github"]
			github = append(github, line)
			PackageClassify["github"] = github
			selectLines = append(selectLines[:x],selectLines[x+1:]...)
		}else{
			x++
		}
		//fmt.Printf("import lib = %s \n",line)
	}
	PackageClassify["other"] = selectLines
	//fmt.Println(PackageClassify)
	//fmt.Println(len(selectLines))

	//str, err := json.Marshal(PackageClassify)
	//if err!=nil{
	//	fmt.Println(err)
	//	return
	//}
	//fmt.Println(string(str))
}

func RemoveRepByLoop(slc []string) []string {
	result := []string{}  // 存放结果
	for i := range slc{
		flag := true
		for j := range result{
			if slc[i] == result[j] {
				flag = false  // 存在重复元素，标识为false
				break
			}
		}
		if flag {  // 标识为false，不添加进结果
			result = append(result, slc[i])
		}
	}
	return result
}

func removeDuplicateElement(addrs []string) []string {
	result := make([]string, 0, len(addrs))
	temp := map[string]struct{}{}
	for _, item := range addrs {
		if _, ok := temp[item]; !ok {
			temp[item] = struct{}{}
			result = append(result, item)
		}
	}
	return result
}

func RemoveRepeatedElement(arr []string) (newArr []string) {
	newArr = make([]string, 0)
	for i := 0; i < len(arr); i++ {
		repeat := false
		for j := i + 1; j < len(arr); j++ {
			if arr[i] == arr[j] {
				repeat = true
				break
			}
		}
		if !repeat {
			newArr = append(newArr, arr[i])
		}
	}
	return
}

func FilterKeywords(keyword string,selectLines *importLines){
	p := *selectLines
	for x:=0;x<len(p);{
		if strings.Contains(p[x],keyword){
			p = append(p[:x],p[x+1:]...)
		}else{
			x++
		}
	}
	*selectLines = p
}


func readGoFileImport(file string,selectLines ...*importLines){
	//fmt.Printf("file index : file_name:%s \n",file)
	f, err := os.Open(file)
	if err != nil {
		panic(err)
	}
	rd := bufio.NewReader(f)
	var dataLines []string
	beginReadIndex,endReadIndex:=0,0
	for {
		line, err := rd.ReadString('\n') //以'\n'为结束符读入一行

		if err != nil || io.EOF == err {
			break
		}
		if strings.Contains(line,"import")&&strings.Contains(line,"("){
			beginReadIndex++
		}else if strings.Contains(line,"import")&&strings.Contains(line,"\""){
			dataLines = append(dataLines,line)
		}
		if strings.Contains(line,")"){
			endReadIndex++
		}
		if beginReadIndex ==1 && endReadIndex==0{
			dataLines = append(dataLines,line)
		}
	}
	if len(dataLines)>1{
		for _,lines := range dataLines{
			if len(strings.TrimSpace(lines))>0 && strings.Contains(lines,"\"") {
				split_line := lines[strings.Index(lines,"\"")+1:strings.LastIndex(lines,"\"")]
				//fmt.Println(split_line)
				*selectLines[0] = append(*selectLines[0], split_line)
			}
		}
	}
}




func GetAllFile(pathname string, s []string) ([]string, error) {
	rd, err := ioutil.ReadDir(pathname)
	if err != nil {
		fmt.Println("read dir fail:", err)
		return s, err
	}
	for _, fi := range rd {
		if fi.IsDir() {
			fullDir := pathname + "/" + fi.Name()
			s, err = GetAllFile(fullDir, s)
			if err != nil {
				fmt.Println("read dir fail:", err)
				return s, err
			}
		} else {
			kfileName := fi.Name()
			if !strings.HasSuffix(kfileName,".go"){
				continue
			}
			fullName := pathname + "/" + kfileName
			s = append(s, fullName)
		}
	}
	return s, nil
}

func GetGolibPackages(gopath string)[]string {
	var libpackages [] string
	GOPATH := gopath + "\\src"
	//fmt.Println(GOPATH)
	rd, err := ioutil.ReadDir(GOPATH)
	if err != nil {
		fmt.Println("read dir fail:", err)
		return nil
	}

	githubName := "github.com"
	for _, file := range rd {
		if file.Name() == githubName {
			locationPath := GOPATH + "\\" + githubName
			rs, fileError := ioutil.ReadDir(locationPath)
			if fileError != nil {
				fmt.Println(fileError)
				break;
			}
			for _, k := range rs {
				m := locationPath + "\\" + k.Name()
				j, u := ioutil.ReadDir(m)
				//fmt.Println(m)
				if u != nil {
					fmt.Println(u)
					continue
				}
				//fmt.Println(j)
				for _, y := range j {
					//fmt.Println(strings.Split(m+"\\"+y.Name(),GOPATH+"\\")[1])
					libpackages = append(libpackages, strings.ReplaceAll(strings.Split(m+"\\"+y.Name(), GOPATH+"\\")[1],"\\","/"))
				}
			}
			break;
		}
	}
	return  libpackages
 }
